package com.flying.flyingchessgame.security.jwt;

import com.flying.flyingchessgame.security.service.UserDetailsServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * JWT认证过滤器
 * <p>
 * 继承OncePerRequestFilter，确保每个请求只执行一次过滤。
 * 用于从HTTP请求中提取JWT令牌，验证令牌，并设置Spring Security上下文。
 * </p>
 * 
 * @author flying-chess
 * @version 1.0
 */
public class AuthTokenFilter extends OncePerRequestFilter {
    
    /**
     * JWT工具类
     */
    @Autowired
    private JwtUtils jwtUtils;

    /**
     * 用户详情服务
     */
    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);

    /**
     * 执行过滤器逻辑
     * <p>
     * 从HTTP请求中提取JWT令牌，验证令牌，并设置Spring Security上下文。
     * </p>
     *
     * @param request HTTP请求
     * @param response HTTP响应
     * @param filterChain 过滤器链
     * @throws ServletException Servlet异常
     * @throws IOException IO异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        try {
            String jwt = parseJwt(request);
            if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
                String username = jwtUtils.getUsernameFromJwtToken(jwt);
                logger.debug("JWT令牌有效，用户: {}", username);

                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(
                                userDetails,
                                null,
                                userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authentication);
                logger.debug("用户已认证: {}", username);
            } else {
                if (jwt != null) {
                    logger.warn("无效的JWT令牌");
                } else {
                    logger.debug("请求中未找到JWT令牌");
                }
            }
        } catch (Exception e) {
            logger.error("无法设置用户认证: {}", e.getMessage());
        }

        filterChain.doFilter(request, response);
    }

    /**
     * 从HTTP请求中解析JWT令牌
     * <p>
     * 从Authorization头部中提取Bearer令牌。
     * </p>
     *
     * @param request HTTP请求
     * @return JWT令牌，如果不存在则返回null
     */
    private String parseJwt(HttpServletRequest request) {
        String headerAuth = request.getHeader("Authorization");

        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
            logger.trace("从请求头解析JWT令牌");
            return headerAuth.substring(7);
        }

        return null;
    }
} 